﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Hypervisor管理工具
{
    /// <summary>
    /// 提供对Hypervisor状态的控制功能，包括启用（自动或强制）、禁用及查询当前状态。
    /// </summary>
    public class HypervisorController
    {
        /// <summary>
        /// 获取根据应用程序架构选择正确的bcdedit.exe路径。
        /// 如果是32位应用在64位系统上运行，则返回Sysnative目录下的路径以避免文件系统重定向。
        /// </summary>
        /// <returns>bcdedit.exe的完整路径。</returns>
        private string GetBcdeditPath()
        {
            if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
            {
                // 对于在64位操作系统上运行的32位进程，使用Sysnative来访问实际的System32目录，
                // 从而绕过Windows的文件系统重定向。
                return Path.Combine(Environment.GetEnvironmentVariable("windir"), "Sysnative", "bcdedit.exe");
            }
            else
            {
                // 对于64位进程或32位系统上的任何进程，使用标准的System32路径。
                return Path.Combine(Environment.GetEnvironmentVariable("windir"), "System32", "bcdedit.exe");
            }
        }

        /// <summary>
        /// 检查指定路径下的bcdedit.exe是否存在。
        /// </summary>
        /// <param name="bcdeditPath">bcdedit.exe的完整路径。</param>
        /// <returns>如果文件存在则返回true，否则返回false。</returns>
        private bool IsBcdeditAvailable(string bcdeditPath)
        {
            return File.Exists(bcdeditPath);
        }

        /// <summary>
        /// 执行给定的命令行指令。
        /// </summary>
        /// <param name="arguments">传递给可执行文件的参数。</param>
        private void ExecuteCommand(string arguments)
        {
            string bcdeditPath = GetBcdeditPath();
            if (!IsBcdeditAvailable(bcdeditPath))
            {
                throw new FileNotFoundException("无法找到 bcdedit.exe", bcdeditPath);
            }

            using (Process process = new Process())
            {
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    WindowStyle = ProcessWindowStyle.Hidden,
                    FileName = bcdeditPath,
                    Arguments = arguments,
                    Verb = "runas", // 请求管理员权限
                    RedirectStandardError = true,
                    RedirectStandardOutput = true,
                    UseShellExecute = false
                };
                process.StartInfo = startInfo;
                try
                {
                    process.Start();
                    string output = process.StandardOutput.ReadToEnd();
                    string error = process.StandardError.ReadToEnd();
                    process.WaitForExit();

                    if (!string.IsNullOrEmpty(error))
                    {
                        Console.WriteLine("执行命令时出错: " + error);
                    }
                    else
                    {
                        Console.WriteLine(output);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"无法执行命令: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 获取当前Hypervisor的状态。
        /// </summary>
        /// <returns>包含当前Hypervisor状态的字符串。</returns>
        public string GetCurrentHypervisorStatus()
        {
            string bcdeditPath = GetBcdeditPath();
            if (!IsBcdeditAvailable(bcdeditPath))
            {
                throw new FileNotFoundException("无法找到 bcdedit.exe", bcdeditPath);
            }

            using (Process process = new Process())
            {
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    WindowStyle = ProcessWindowStyle.Hidden,
                    FileName = bcdeditPath,
                    Arguments = "/enum {current}",
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    Verb = "runas" // 请求管理员权限
                };

                process.StartInfo = startInfo;
                process.Start();

                string result = process.StandardOutput.ReadToEnd();
                process.WaitForExit();

                foreach (var line in result.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries))
                {
                    if (line.Contains("hypervisorlaunchtype"))
                    {
                        return line.Trim();
                    }
                }
                return "未找到Hypervisor状态";
            }
        }

        /// <summary>
        /// 设置Hypervisor为自动加载模式。
        /// </summary>
        public void EnableAuto()
        {
            ExecuteCommand("/set hypervisorlaunchtype Auto");
        }

        /// <summary>
        /// 强制启用Hypervisor。
        /// </summary>
        //public void EnableForce()
        //{
        //    ExecuteCommand("/set hypervisorlaunchtype On");
        //}

        /// <summary>
        /// 禁用Hypervisor。
        /// </summary>
        public void Disable()
        {
            ExecuteCommand("/set hypervisorlaunchtype Off");
        }
    }
}
